#!/usr/bin/env python

""" 
    RTLCode module provided all the kinds RTL code.
"""
__author__ = 'liwei79@gmail.com'

from RTLOperand import *
from RTLOperator import *

class RTLCode:
    """ 
        Base Class for all kinds of RTL code 
        And any kind of RTLCode will have an operator(op) 
    """

    def __init__(self, op):
        self.op = op


class RTLCodeHasRet:
    """ 
        Interface virtual class.
        Indicate that such RTLCode has return 
        operand. The return can't be a number.
    """

    def __init__(self, ret):
        self.ret =  ret
        assert(not isinstance(ret, OpndNum))

    def getRet(self):
        return self.ret

class RTLCodeHasFuncLst:
    """
        Interface virtual class.
        Such RTL code contains a funtion/call name. And a list of 
        operands.
    """

    def __init__(self, funcname, lst):
        self.funcname = funcname
        self.lst = lst

    def getOpndLst(self):
        return self.lst


class CodeBop(RTLCode, RTLCodeHasRet):
    """ Binary RTL code """

    def __init__(self, op, ret, opnd1, opnd2):
        RTLCode.__init__(self, op)
        RTLCodeHasRet.__init__(self, ret)
        self.opnd1 = opnd1
        self.opnd2 = opnd2

    def __repr__(self):
        return "\tBOP:\t[%10s]  [%s %s %s]" % (self.op, self.ret, self.opnd1, self.opnd2)
    

class CodeUop(RTLCode, RTLCodeHasRet):
    """ Unary RTL code """

    def __init__(self, op, ret, opnd1):
        RTLCode.__init__(self, op)
        RTLCodeHasRet.__init__(self, ret)
        self.opnd1 = opnd1

    def __repr__(self):
        return "\tUOP:\t[%10s]  [%s %s]" % (self.op, self.ret, self.opnd1)


class CodeRout(RTLCode, RTLCodeHasFuncLst):
    """ Routine definition code """

    def __init__(self, funcname, lst):
        RTLCode.__init__(self, OpRout("ROUT"))
        RTLCodeHasFuncLst.__init__(self, funcname, lst)

    def __repr__(self):
        return "\t======ROUT START:\t%s %s ========" % (self.funcname, self.lst)


class CodeCall(RTLCode, RTLCodeHasFuncLst):
    """ Call """

    def __init__(self, funcname, lst):
        RTLCode.__init__(self, OpCall("CALL"))
        RTLCodeHasFuncLst.__init__(self, funcname, lst)

    def __repr__(self):
        return "\tCALL:\t[%10s]  [%s%s]" % ("", self.funcname, self.lst)
    

class CodeFunc(RTLCode, RTLCodeHasFuncLst, RTLCodeHasRet):
    """ Function """

    def __init__(self, ret, funcname, lst):
        RTLCode.__init__(self, OpFunc("FUNC"))
        RTLCodeHasRet.__init__(self, ret)
        RTLCodeHasFuncLst.__init__(self, funcname, lst)

    def __repr__(self):
        return "\tFUNC:\t[%7s = ]  [%s%s]" % (self.ret, self.funcname, self.lst)

class CodeRet(RTLCode, RTLCodeHasRet):
    """ RET code """

    def __init__(self, ret):
        RTLCode.__init__(self, OpRet("RET"))
        RTLCodeHasRet.__init__(self, ret)

    def __repr__(self):
        return "\tRET:\t[%10s]  [%s]" % ("ret", self.ret)

if __name__ == "__main__":
    print CodeRout("foo", OpndLst([OpndReg("a"), OpndReg("b"), OpndReg("c")]))
    print CodeBop(OpBinary("ADD"), OpndReg("a"), OpndReg("b"), OpndNum(10))
    print CodeUop(OpUnary("BINV"), OpndReg("a"), OpndNum(20))
    print CodeCall("bar", OpndLst([OpndReg("a"), OpndReg("b"), OpndReg("c")]))
    print CodeFunc(OpndReg("r"), "bar", OpndLst([OpndReg("a"), OpndReg("b"), OpndReg("c")]))
    print CodeRet(OpndReg("a"))
